package com.zhongwang.mms.module.jiaGongMaterial.service;

import com.zhongwang.mms.gen.entity.*;
import com.zhongwang.mms.module.allocation.dao.AllocationOrderDao;
import com.zhongwang.mms.module.basic.dao.MMaterialsDao;
import com.zhongwang.mms.module.basic.model.MMaterialsModel;
import com.zhongwang.mms.module.basic.service.BoardService;
import com.zhongwang.mms.module.jiaGongMaterial.dao.MaterialInDao;
import com.zhongwang.mms.module.jiaGongMaterial.model.*;
import com.zhongwang.mms.module.material.dao.MChangeOrderDao;
import com.zhongwang.mms.module.material.dao.MInventoryDao;
import com.zhongwang.mms.module.material.dao.MOrderDao;
import com.zhongwang.mms.module.material.dao.MOrderDetailDao;
import com.zhongwang.mms.module.material.model.MOrderDetailModel;
import com.zhongwang.mms.module.material.model.MProCodeQueryModel;
import com.zhongwang.mms.module.material.service.MInventoryService;
import com.zhongwang.mms.module.overview.model.ProjectStatusModel;
import com.zhongwang.mms.module.system.log.LogService;
import com.zhongwang.mms.util.BigDecimalUtils;
import com.zhongwang.mms.util.ShiroUtils;
import lombok.extern.log4j.Log4j2;
import lombok.var;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

/**
 * @Description: 原料出入库 服务层
 * @Author: China.wsg
 * @Date: 2020/04/01 11:23
 */
@Log4j2
@Service
public class MaterialInService {

    @Autowired
    private MMaterialsDao materialsDao;
    @Autowired
    private MOrderDao orderDao;
    @Autowired
    private MOrderDetailDao orderDetailDao;
    @Autowired
    private LogService logService;
    @Autowired
    private MInventoryService inventoryService;
    @Autowired
    private MInventoryDao inventoryDao;
    @Autowired
    private MChangeOrderDao changeOrderDao;
    @Autowired
    private BoardService boardService;
    @Autowired
    private AllocationOrderDao allocationOrderDao;
    @Autowired
    private MaterialInDao materialInDao;

    /**
     * 创建原料入库单
     *
     * @param jMaterialInsertModel
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public String saveInOrderModel(JMaterialInsertModel jMaterialInsertModel) {
        String msg = "";  // 返回提示信息
        try {
            // 1 校验保存数据可用性、存在不满足条件数据 整单不允许保存
            msg = checkInValidate(jMaterialInsertModel, msg);
            if (msg.length() > 0) {
                msg = msg + "<br>单据保存失败，请先维护以上原料信息！";
                return msg;
            }
            // 保存主单信息
            JMaterial jMaterial = saveOrder(jMaterialInsertModel, 1);
            // 保存单据明细信息和库存在库(入库)
            saveInOrderDetail(jMaterialInsertModel, jMaterial);
            logService.saveLog("保存甲供件-原料入库单", "单据编号：" + jMaterial.getOdrCode() + "<br>单据类型：" + (jMaterial.getOdrType() == 1 ? "采购入库" : jMaterial.getOdrType() == 2 ? "车间返料" : "调拨入库"));
            return "单据保存成功！";
        } catch (Exception e) {
            e.printStackTrace();
            log.error(e.getMessage());
            return "填写数据格式错误！";
        }
    }

    /**
     * 创建原料出库单
     *
     * @param jMaterialInsertModel
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public String saveOutOrderModel(JMaterialInsertModel jMaterialInsertModel) {

        String msg = "";  // 返回提示信息

        // 1 校验保存数据可用性、存在不满足条件数据 整单不允许保存
        msg = checkOutValidate(jMaterialInsertModel, msg);
        if (msg.length() > 0) {
            msg = msg + "<br>可用在库库存量不足，保存失败！";
            return msg;
        }

        // 保存主单信息
        JMaterial jMaterial = saveOrder(jMaterialInsertModel, 2);

        // 保存单据明细信息和库存在库(出库)
        saveOutOrderDetail(jMaterialInsertModel, jMaterial);

        logService.saveLog("保存原料出库单", "单据编号：" + jMaterial.getOdrCode() + "<br>单据类型：" + (jMaterial.getOdrType() == 4 ? "领料出库" : "调拨出库"));
        return jMaterial.getOdrId() == null ? "保存失败" : jMaterial.getOdrId().toString();
    }

    /**
     * 校验入库单数据可用性
     *
     * @param jMaterialInsertModel
     * @return
     */
    private String checkInValidate(JMaterialInsertModel jMaterialInsertModel, String msg) {

        // 循环判断原料基础信息是否存在（提示内容：第N行 类型_材质_规格 长*宽*高 基础信息不存在）
        JMaterialsModel jMaterialsModel;
        for (var i = 0; i < jMaterialInsertModel.getInsertData().size(); i++) {
            String matTypeName = jMaterialInsertModel.getInsertData().get(i).getMatType().replace("\n", "").replace(" ", "");
            String matQualityName = jMaterialInsertModel.getInsertData().get(i).getMatQuality().replace("\n", "").replace(" ", "");
            String matSpecName = jMaterialInsertModel.getInsertData().get(i).getMatSpec().replace("\n", "").replace(" ", "");
            Double matWidth = jMaterialInsertModel.getInsertData().get(i).getMatWidth();
            Double matLength = jMaterialInsertModel.getInsertData().get(i).getMatLength();
            Double matHeight = jMaterialInsertModel.getInsertData().get(i).getMatHeight();

//            // 添加查询条件
//            jMaterialsModel = new JMaterialsModel();
//            jMaterialsModel.setMatTypeName(matTypeName);
//            jMaterialsModel.setMatQualityName(matQualityName);
//            jMaterialsModel.setMatSpecName(matSpecName);
//            jMaterialsModel.setMatWidth(matWidth);
//            jMaterialsModel.setMatLength(matLength);
//            jMaterialsModel.setMatHeight(matHeight);
//
//            List<MMaterials> materials = materialInDao.findMaterialsByQuery(jMaterialsModel);
//            // 判断原料基础信息是否存在
//            if (materials == null || materials.size() <= 0) {
//                msg = msg + "<br>第" + (i + 1) + "行" + " " + matTypeName + "_" + matQualityName + "_" + matSpecName + "  " + matWidth + "*" + matLength + "*" + matHeight + "基础信息不存在";
//            }

            // 判断 入库明细中【在库类型】字段为空，不允许入库
            if (jMaterialInsertModel.getInsertData().get(i).getOdaInTypeName() == null || jMaterialInsertModel.getInsertData().get(i).getOdaInTypeName() == "") {
                msg = msg + "<br>第" + (i + 1) + "行" + " 在库类型 为空";
            }

            // 判断 入库明细中【重量】字段为空，不允许入库
            if (jMaterialInsertModel.getInsertData().get(i).getOdaWeight() == null) {
                msg = msg + "<br>第" + (i + 1) + "行" + " 重量 为空";
            }
            // 判断 入库明细中 项目在库【项目编号】字段为空，不允许入库
            if (jMaterialInsertModel.getInsertData().get(i).getOdaInTypeName().equals("项目在库")
                    && ("".equals(jMaterialInsertModel.getInsertData().get(i).getOdaProCode()) || jMaterialInsertModel.getInsertData().get(i).getOdaProCode() == null)) {
                msg = msg + "<br>第" + (i + 1) + "行" + " 项目编号 为空";
            }
            // 判断 项目编码不存在不允许入库
            MProCodeQueryModel proCodeQueryModel = new MProCodeQueryModel();
            proCodeQueryModel.setProCode(boardService.projectCodeHandle(jMaterialInsertModel.getInsertData().get(i).getOdaProCode()));
            List<ProjectStatusModel> projectStatusModels = orderDetailDao.findProjectByCode(proCodeQueryModel);
            if (jMaterialInsertModel.getInsertData().get(i).getOdaInTypeName().equals("项目在库")
                    && !"".equals(jMaterialInsertModel.getInsertData().get(i).getOdaProCode())
                    && jMaterialInsertModel.getInsertData().get(i).getOdaProCode() != null
                    && (projectStatusModels == null || projectStatusModels.size() == 0)) {
                msg = msg + "<br>第" + (i + 1) + "行" + " 项目编码不存在";
            }
        }
        return msg;
    }

    /**
     * 校验出库单数据可用性
     *
     * @param jMaterialInsertModel
     * @return
     */
    private String checkOutValidate(JMaterialInsertModel jMaterialInsertModel, String msg) {

        // 循环判断可用在库库存量是否充足（提示内容：类型_材质_规格 长*宽*高 可用在库库存量不足，保存失败！）
        JMaterialInventory jMaterialInventory;
        JMaterialDetail jMaterialDetail;
        List<JMaterialDetail> jMaterialDetails = new ArrayList<>();

        for (int i = 0; i < jMaterialInsertModel.getInsertData().size(); i++) {
            if (jMaterialInsertModel.getInsertData().get(i).getItyId() == null) {
                continue;
            }

            // 同张单据多条数据相同时，需要将出库数量累加之后再进行库存是否充足校验
            boolean sameFlg = false;
            for (int j = 0; j < jMaterialDetails.size(); j++) {

                if (sameFlg) {
                    break;
                }

                Integer insertDetailId = jMaterialInsertModel.getInsertData().get(i).getItyId();
                Integer outDetailId = jMaterialDetails.get(j).getItyId();
                if (insertDetailId.intValue() == outDetailId.intValue()) {
                    jMaterialDetails.get(j).setOdaNum(BigDecimalUtils.add(jMaterialDetails.get(j).getOdaNum(), jMaterialInsertModel.getInsertData().get(i).getOdaNum()));
                    jMaterialDetails.get(j).setOdaWeight(BigDecimalUtils.add(jMaterialDetails.get(j).getOdaWeight(), jMaterialInsertModel.getInsertData().get(i).getOdaWeight()));
                    sameFlg = true;
                }
            }

            if (!sameFlg) {
                jMaterialDetail = new JMaterialDetail();
                jMaterialDetail.setItyId(jMaterialInsertModel.getInsertData().get(i).getItyId());
                jMaterialDetail.setOdaNum(jMaterialInsertModel.getInsertData().get(i).getOdaNum());
                jMaterialDetail.setOdaWeight(jMaterialInsertModel.getInsertData().get(i).getOdaWeight());
                jMaterialDetails.add(jMaterialDetail);
            }
        }

        for (var i = 0; i < jMaterialDetails.size(); i++) {

            // 取得原料在库明细信息，与实际出库量进行比对，判断库存是否充足
            jMaterialInventory = materialInDao.selectByPrimaryKey(jMaterialDetails.get(i).getItyId());

            double a = jMaterialInventory.getItyAvaNum();
            double b = jMaterialInventory.getItyAvaWeight();
            double c = jMaterialDetails.get(i).getOdaNum();
            double d = jMaterialDetails.get(i).getOdaWeight();
            if (a < c || b < d) {

                String wrongInfo = jMaterialInsertModel.getInsertData().get(i).getMatType() + "_"
                        + jMaterialInsertModel.getInsertData().get(i).getMatQuality() + "_"
                        + jMaterialInsertModel.getInsertData().get(i).getMatSpec() + "  "
                        + jMaterialInsertModel.getInsertData().get(i).getMatWidth() + "*"
                        + jMaterialInsertModel.getInsertData().get(i).getMatLength() + "*"
                        + jMaterialInsertModel.getInsertData().get(i).getMatHeight();
                msg = msg + "<br>" + wrongInfo;
            }
        }
        return msg;
    }

    /**
     * 保存主单信息
     *
     * @param jMaterialInsertModel
     * @param inOutType            出入库区分 1：入库 2：出库
     * @return
     */
    private JMaterial saveOrder(JMaterialInsertModel jMaterialInsertModel, Integer inOutType) {

        JMaterial jMaterial = new JMaterial();

        // 取得当日零时时间
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(new Date());
        calendar.set(Calendar.HOUR_OF_DAY, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        Date date = calendar.getTime();

        // 获取单据编号
        MOrderExample ex = new MOrderExample();
        ex.setOrderByClause("odr_id desc");
        MOrderExample.Criteria criteria = ex.createCriteria();
        criteria.andOdrMakeDateGreaterThan(date);
        criteria.andOdrRedFlagEqualTo(1);
        if (inOutType == 1) {
            criteria.andOdrTypeIn(new ArrayList<Integer>() {{
                add(1); // 采购入库
                add(2); // 车间返料入库
                add(6); // 调拨入库
            }});
        } else if (inOutType == 2) {
            criteria.andOdrTypeIn(new ArrayList<Integer>() {{
                add(4); // 领料出库
                add(5); // 调拨出库
            }});
        }
        List<JMaterial> jMaterials = materialInDao.selectByExample(ex);
        String billCode; // 入库编码：MRK+年月日+3位流水号 MRK200317001，出库编码 MCK200317001
        String prefix = "";  // 单据编号前缀
        if (inOutType == 1) {
            prefix = "MRK";
        } else if (inOutType == 2) {
            prefix = "MCK";
        }
        // 获取单据编号
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
        if (jMaterials != null && jMaterials.size() > 0) {
            billCode = prefix + dateFormat.format(new Date()).substring(2) + String.format("%0" + 3 + "d", Integer.parseInt(jMaterials.get(0).getOdrCode().substring(9, 12)) + 1);
        } else {
            billCode = prefix + dateFormat.format(new Date()).substring(2) + "001";
        }

        if (jMaterialInsertModel.getFormData() != null) {
            jMaterial = jMaterialInsertModel.getFormData();
        }

        jMaterial.setOdrCode(billCode);
        jMaterial.setOdrMakeDate(new Date());
        jMaterial.setOdrMakePerson(ShiroUtils.getUser().getName());
        jMaterial.setOdrItyFlag(1);
        jMaterial.setOdrRedFlag(1);

        // 自动填充备注信息
        if (jMaterial.getOdrRemark() == null || jMaterial.getOdrRemark() == "") {
            String inTypeNm = "";
            if (jMaterial.getOdrType() == 1) {
                inTypeNm = "采购入库";
            } else if (jMaterial.getOdrType() == 2) {
                inTypeNm = "退料入库";
            } else if (jMaterial.getOdrType() == 4) {
                inTypeNm = "领料出库";
            } else if (jMaterial.getOdrType() == 5) {
                inTypeNm = "调拨出库";
            } else if (jMaterial.getOdrType() == 6) {
                inTypeNm = "调拨入库";
            }
            String handler = jMaterial.getOdrTakePerson() == null ? "" : jMaterial.getOdrTakePerson();
            String mtType = jMaterialInsertModel.getInsertData().get(0).getMatType().replace("\n", "").replace(" ", "");
            String mtQuality = jMaterialInsertModel.getInsertData().get(0).getMatQuality().replace("\n", "").replace(" ", "");
            String mtSpec = jMaterialInsertModel.getInsertData().get(0).getMatSpec().replace("\n", "").replace(" ", "");
            Double mtWidth = jMaterialInsertModel.getInsertData().get(0).getMatWidth();
            Double mtLength = jMaterialInsertModel.getInsertData().get(0).getMatLength();
            Double mtHeight = jMaterialInsertModel.getInsertData().get(0).getMatHeight();
            String trackCd = jMaterialInsertModel.getInsertData().get(0).getOdaTrackCode();
            String materialNm = mtType + "_" + mtQuality + "_" + mtSpec + "  " + mtWidth + "*" + mtLength + "*" + mtHeight;
            jMaterial.setOdrRemark(inTypeNm + ":" + trackCd + " 【" + materialNm + "】等:" + handler);
        }

        // 保存主单
        materialInDao.insert(jMaterial);
        return jMaterial;
    }

    /**
     * 保存单据明细信息和库存在库（入库单）
     *
     * @param jMaterialInsertModel
     * @param jMaterial
     */
    private void saveInOrderDetail(JMaterialInsertModel jMaterialInsertModel, JMaterial jMaterial) {

        // 循环orderDetail明细数据 同时赋值入库明细实体
        JMaterialDetail jMaterialDetail;
        JMaterialInventory jMaterialInventory;
        MOrderDetailModel orderDetailModel;
        for (var i = 0; i < jMaterialInsertModel.getInsertData().size(); i++) {

            // 封装入库明细单实体并保存
            // 取得前台表单明细信息
            orderDetailModel = new MOrderDetailModel();
            orderDetailModel.setMatType(jMaterialInsertModel.getInsertData().get(i).getMatType().replace("\n", "").replace(" ", ""));
            orderDetailModel.setMatQuality(jMaterialInsertModel.getInsertData().get(i).getMatQuality().replace("\n", "").replace(" ", ""));
            orderDetailModel.setMatSpec(jMaterialInsertModel.getInsertData().get(i).getMatSpec().replace("\n", "").replace(" ", ""));
            orderDetailModel.setMatWidth(jMaterialInsertModel.getInsertData().get(i).getMatWidth());
            orderDetailModel.setMatLength(jMaterialInsertModel.getInsertData().get(i).getMatLength());
            orderDetailModel.setMatHeight(jMaterialInsertModel.getInsertData().get(i).getMatHeight());
            // 四舍五入
            orderDetailModel.setOdaNum((double) Math.round((jMaterialInsertModel.getInsertData().get(i).getOdaNum() == null ? 0.00 : jMaterialInsertModel.getInsertData().get(i).getOdaNum()) * 100) / 100);
            // 四舍五入
            orderDetailModel.setOdaWeight((double) Math.round((jMaterialInsertModel.getInsertData().get(i).getOdaWeight() == null ? 0.00 : jMaterialInsertModel.getInsertData().get(i).getOdaWeight()) * 100) / 100);
            // 四舍五入
//            orderDetailModel.setOdaPrice((double) Math.round((jMaterialInsertModel.getInsertData().get(i).getOdaPrice() == null ? 0.00 : jMaterialInsertModel.getInsertData().get(i).getOdaPrice()) * 1000) / 1000);
//            // 四舍五入
//            Double receivePrice = jMaterialInsertModel.getInsertData().get(i).getOdaPrice() == null ? 0.00 : jMaterialInsertModel.getInsertData().get(i).getOdaPrice();
//            Double receiveWeight = jMaterialInsertModel.getInsertData().get(i).getOdaWeight() == null ? 0.00 : jMaterialInsertModel.getInsertData().get(i).getOdaWeight();
//            Double receiveAmountMoney = BigDecimalUtils.mul(receivePrice, receiveWeight);
//            orderDetailModel.setOdaAmount((double) Math.round((receiveAmountMoney) * 1000) / 1000);
            orderDetailModel.setOdaTrackCode(jMaterialInsertModel.getInsertData().get(i).getOdaTrackCode());
            orderDetailModel.setOdaProCode(boardService.projectCodeHandle(jMaterialInsertModel.getInsertData().get(i).getOdaProCode()));
            orderDetailModel.setOdaProName(jMaterialInsertModel.getInsertData().get(i).getOdaProName());
            orderDetailModel.setOdaInType("库存在库".equals(jMaterialInsertModel.getInsertData().get(i).getOdaInTypeName()) ? 1 : 2);
            orderDetailModel.setOdaBackDate(jMaterialInsertModel.getInsertData().get(i).getOdaBackDate());
            orderDetailModel.setOdaBackWeight(jMaterialInsertModel.getInsertData().get(i).getOdaBackWeight());
            orderDetailModel.setOdaSpec(jMaterialInsertModel.getInsertData().get(i).getOdaSpec() == null ? "" : jMaterialInsertModel.getInsertData().get(i).getOdaSpec());
            orderDetailModel.setOdaMatSapCode(jMaterialInsertModel.getInsertData().get(i).getOdaMatSapCode());
            orderDetailModel.setOdaPosition(jMaterialInsertModel.getInsertData().get(i).getOdaPosition());
            orderDetailModel.setOdaWhiId(jMaterialInsertModel.getFormData().getOdrWhiId());

            // 取得原料实体 、添加查询条件
            MMaterialsModel materialsModel = new MMaterialsModel();
            materialsModel.setMatTypeName(orderDetailModel.getMatType());
            materialsModel.setMatQualityName(orderDetailModel.getMatQuality());
            materialsModel.setMatSpecName(orderDetailModel.getMatSpec());
            materialsModel.setMatWidth(orderDetailModel.getMatWidth());
            materialsModel.setMatLength(orderDetailModel.getMatLength());
            materialsModel.setMatHeight(orderDetailModel.getMatHeight());

           List<MMaterials>  materials = materialsDao.findMaterialsByQuery(materialsModel);

            // 执行库存在库表入库
            // 分装在库表单实体
            jMaterialInventory = new JMaterialInventory();
            if (materials.size()>0 ){

                jMaterialInventory.setItyMatId(materials.get(0).getMatId());
            }else {
                jMaterialInventory.setItyMatId(0);
            }
            jMaterialInventory.setItyInType(orderDetailModel.getOdaInType());
            jMaterialInventory.setItyProCode(orderDetailModel.getOdaProCode());
            jMaterialInventory.setItyProName(orderDetailModel.getOdaProName());
            jMaterialInventory.setItySpec(orderDetailModel.getOdaSpec());
            jMaterialInventory.setItyTrackCode(orderDetailModel.getOdaTrackCode());
            jMaterialInventory.setItyNum(orderDetailModel.getOdaNum());
            jMaterialInventory.setItyWeight(orderDetailModel.getOdaWeight());
            jMaterialInventory.setItyAvaNum(orderDetailModel.getOdaNum());
            jMaterialInventory.setItyAvaWeight(orderDetailModel.getOdaWeight());
            jMaterialInventory.setItyBackDate(orderDetailModel.getOdaBackDate());
//            jMaterialInventory.setItyPrice(orderDetailModel.getOdaPrice());
            jMaterialInventory.setItyStoId(jMaterial.getOdrWhiId());
            jMaterialInventory.setItyMatSapCode(orderDetailModel.getOdaMatSapCode());
            jMaterialInventory.setItyPosition(orderDetailModel.getOdaPosition());
            jMaterialInventory.setMatHeight(orderDetailModel.getMatHeight());
            jMaterialInventory.setMatLength(orderDetailModel.getMatLength());
            jMaterialInventory.setMatQuality(orderDetailModel.getMatQuality());
            jMaterialInventory.setMatWidth(orderDetailModel.getMatWidth());
            jMaterialInventory.setMatType(orderDetailModel.getMatType());
            jMaterialInventory.setMatSpec(orderDetailModel.getMatSpec());
            jMaterialInventory.setSupplier(jMaterialInsertModel.getInsertData().get(i).getSupplier());
            jMaterialInventory.setContractNo(jMaterialInsertModel.getInsertData().get(i).getContractNo());
            // 执行插入操作
            materialInDao.insertJMaterialInventory(jMaterialInventory);
//            // 入库类型：1=采购入库 2=车间返料
//            if (jMaterial.getOdrType() == 1 ||jMaterial.getOdrType() == 6) {
//                jMaterialInventory = inventoryService.addInventory(jMaterialInventory, 1);
//            } else {
//                jMaterialInventory = inventoryService.addInventory(jMaterialInventory, 2);
//            }

            // 保存单据明细
            jMaterialDetail = new JMaterialDetail();
            jMaterialDetail.setMatHeight(orderDetailModel.getMatHeight());
            jMaterialDetail.setMatLength(orderDetailModel.getMatLength());
            jMaterialDetail.setMatQuality(orderDetailModel.getMatQuality());
            jMaterialDetail.setMatWidth(orderDetailModel.getMatWidth());
            jMaterialDetail.setMatType(orderDetailModel.getMatType());
            jMaterialDetail.setMatSpec(orderDetailModel.getMatSpec());
            jMaterialDetail.setOdaInType(orderDetailModel.getOdaInType());
            jMaterialDetail.setOdaProCode(orderDetailModel.getOdaProCode());
            jMaterialDetail.setOdaProName(orderDetailModel.getOdaProName());
            jMaterialDetail.setOdaNum(orderDetailModel.getOdaNum());
            jMaterialDetail.setOdaWeight(orderDetailModel.getOdaWeight());
            jMaterialDetail.setOdaBackDate(orderDetailModel.getOdaBackDate());
            jMaterialDetail.setOdaTrackCode(orderDetailModel.getOdaTrackCode());
            jMaterialDetail.setOdaOdrId(jMaterial.getOdrId());
            if (materials.size()>0 ){
                jMaterialDetail.setOdaMatId(materials.get(0).getMatId());
            }else {
                jMaterialDetail.setOdaMatId(0);
            }
            jMaterialDetail.setOdaSpec(orderDetailModel.getOdaSpec());
            jMaterialDetail.setOdaBackWeight(orderDetailModel.getOdaBackWeight());
//            jMaterialDetail.setOdaPrice(orderDetailModel.getOdaPrice());
//            jMaterialDetail.setOdaAmount(orderDetailModel.getOdaAmount());
            jMaterialDetail.setOdaItyFlag(1);
            jMaterialDetail.setOdaRedFlag(1);
            jMaterialDetail.setOdaMatSapCode(orderDetailModel.getOdaMatSapCode());
            jMaterialDetail.setOdaItyId(jMaterialInventory.getItyId());
            jMaterialDetail.setOdaPosition(jMaterialInventory.getItyPosition());
            jMaterialDetail.setOdaWhiId(jMaterialInventory.getItyStoId());
            jMaterialDetail.setSupplier(jMaterialInsertModel.getInsertData().get(i).getSupplier());
            jMaterialDetail.setContractNo(jMaterialInsertModel.getInsertData().get(i).getContractNo());
            materialInDao.insertJMaterialDetail(jMaterialDetail);
        }
    }

    /**
     * 保存单据明细信息和库存在库（出库单）
     *
     * @param jMaterialInsertModel
     * @param jMaterial
     */
    private void saveOutOrderDetail(JMaterialInsertModel jMaterialInsertModel, JMaterial jMaterial) {

        // 循环orderDetail明细数据 同时赋值入库明细实体
        JMaterialDetail jMaterialDetail;
        JMaterialInventory jMaterialInventory;
        for (var i = 0; i < jMaterialInsertModel.getInsertData().size(); i++) {

            if (jMaterialInsertModel.getInsertData().get(i).getItyId() == null) {
                continue;
            }
            // 取得原料在库信息
            jMaterialInventory = materialInDao.selectByPrimaryKey(jMaterialInsertModel.getInsertData().get(i).getItyId());
            // 保存单据明细
            jMaterialDetail = new JMaterialDetail();
            jMaterialDetail.setOdaInType(jMaterialInventory.getItyInType());
            jMaterialDetail.setOdaProCode(jMaterialInsertModel.getInsertData().get(i).getOdaProCode());
            jMaterialDetail.setOdaProName(jMaterialInsertModel.getInsertData().get(i).getOdaProName());
            jMaterialDetail.setOdaNum(jMaterialInsertModel.getInsertData().get(i).getOdaNum());
            jMaterialDetail.setOdaWeight(jMaterialInsertModel.getInsertData().get(i).getOdaWeight());
            jMaterialDetail.setOdaBackDate(jMaterialInventory.getItyBackDate());
            jMaterialDetail.setOdaTrackCode(jMaterialInventory.getItyTrackCode());
            jMaterialDetail.setOdaOdrId(jMaterial.getOdrId());
            jMaterialDetail.setOdaMatId(jMaterialInventory.getItyMatId());
            jMaterialDetail.setOdaSpec(jMaterialInsertModel.getInsertData().get(i).getOdaSpec());
//            jMaterialDetail.setOdaPrice(jMaterialInventory.getItyPrice());
//            jMaterialDetail.setOdaAmount(BigDecimalUtils.mul(jMaterialInventory.getItyPrice(), jMaterialDetail.getOdaWeight()));
            jMaterialDetail.setOdaItyId(jMaterialInventory.getItyId());
            jMaterialDetail.setOdaItyFlag(1);
            jMaterialDetail.setSupplier(jMaterialInventory.getSupplier());
            jMaterialDetail.setContractNo(jMaterialInventory.getContractNo());
            jMaterialDetail.setOdaRedFlag(1);
            jMaterialDetail.setOdaMatSapCode(jMaterialInventory.getItyMatSapCode());
            jMaterialDetail.setOdaPosition(jMaterialInventory.getItyPosition());
            jMaterialDetail.setOdaWhiId(jMaterialInventory.getItyStoId());
            jMaterialDetail.setPkMatLength(jMaterialInsertModel.getInsertData().get(i).getPkMatLength());
            jMaterialDetail.setMatHeight(jMaterialInsertModel.getInsertData().get(i).getMatHeight());
            jMaterialDetail.setMatLength(jMaterialInsertModel.getInsertData().get(i).getMatLength());
            jMaterialDetail.setMatQuality(jMaterialInsertModel.getInsertData().get(i).getMatQuality());
            jMaterialDetail.setMatWidth(jMaterialInsertModel.getInsertData().get(i).getMatWidth());
            jMaterialDetail.setMatType(jMaterialInsertModel.getInsertData().get(i).getMatType());
            jMaterialDetail.setMatSpec(jMaterialInsertModel.getInsertData().get(i).getMatSpec());
            materialInDao.insertJMaterialDetail(jMaterialDetail);

            // 执行库存在库表出库
            subInventory(jMaterialInventory, jMaterialInsertModel.getInsertData().get(i).getOdaNum(), jMaterialInsertModel.getInsertData().get(i).getOdaWeight(),
                    jMaterialInsertModel.getInsertData().get(i).getOdaNum(), jMaterialInsertModel.getInsertData().get(i).getOdaWeight());

        }
    }
    /**
     * 库存在库出库方法（通用）
     *
     * @param jMaterialInventory 待改库存记录
     * @param outNum    出库数量
     * @param outWeight 出库重量
     * @param avaNum    减少可用数量
     * @param avaWeight 减少可用重量
     * @return
     */
    public int subInventory(JMaterialInventory jMaterialInventory, Double outNum, Double outWeight, Double avaNum, Double avaWeight) {

        jMaterialInventory.setItyNum(BigDecimalUtils.sub(jMaterialInventory.getItyNum(), outNum));
        jMaterialInventory.setItyWeight(BigDecimalUtils.sub(jMaterialInventory.getItyWeight(), outWeight));
        jMaterialInventory.setItyAvaNum(BigDecimalUtils.sub(jMaterialInventory.getItyAvaNum(), avaNum));
        jMaterialInventory.setItyAvaWeight(BigDecimalUtils.sub(jMaterialInventory.getItyAvaWeight(), avaWeight));
        return materialInDao.updateByPrimaryKey(jMaterialInventory);
    }
    /**
     * 明细红冲（单条红冲）
     *
     * @param odaId 明细Id
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public String redDetailSingle(Integer odaId) {

        String msg = "";  // 返回提示信息
        String errorReason;

        // 取得单据及明细信息
        MOrderDetail orderDetail = orderDetailDao.selectByPrimaryKey(odaId);
        MOrder order = orderDao.selectByPrimaryKey(orderDetail.getOdaOdrId());
        MInventory inventory = inventoryDao.selectByPrimaryKey(orderDetail.getOdaItyId());
        MMaterials material = materialsDao.selectByPrimaryKey(orderDetail.getOdaMatId());

        // 校验是否满足红冲条件
        errorReason = checkRedValidate(order, orderDetail, inventory, material);
        if (errorReason.length() == 0) {

            //满足冲单条件 执行冲单操作
            redOrderDetailMethod(order, orderDetail, inventory);
        } else {
            msg = msg + errorReason + "  ，红冲失败！";
        }

        logService.saveLog("红冲单据明细", "单据编号：" + order.getOdrCode() + "<br> 原料描述：" + material.getMatNameDesc()
                + "<br> 跟踪号：" + orderDetail.getOdaTrackCode() + "<br> 项目信息" + orderDetail.getOdaProCode() + "  " + orderDetail.getOdaProName()
                + "<br> 重量：" + orderDetail.getOdaWeight());
        return msg.length() > 0 ? msg : "红冲成功！";
    }

    /**
     * 明细红冲（批量红冲）
     *
     * @param arr 明细Id集合
     * @return
     */
    @Transactional(rollbackFor = Exception.class)
    public String redDetailTogether(List<Integer> arr) {

        String msg = "";  // 返回提示信息
        String errorReason; // 红冲校验原因
        int errorCount = 0; // 审核失败记录数
        int successCount = 0; // 成功审核记录数
        MOrderDetail orderDetail;
        MOrder order;
        MInventory inventory;
        MMaterials material;

        int count = orderDetailDao.selectCountDetailByOdaIds(arr);
        int detailOutCount = orderDetailDao.selectDetailCountByRepCode(arr);
        int detailInCount = orderDetailDao.selectDetailInCountByRepCode(arr);
        if (count > 1) {
            msg = "红冲失败！不是同一调拨单";
            return msg;
        } else if (arr.size() != detailOutCount && arr.size() != detailInCount && count == 1) {
            msg = "红冲失败！调拨单明细未全选中";
            return msg;
        }

        for (int i = 0; i < arr.size(); i++) {

            // 取得单据及明细信息
            orderDetail = orderDetailDao.selectByPrimaryKey(arr.get(i));
            order = orderDao.selectByPrimaryKey(orderDetail.getOdaOdrId());
            inventory = inventoryDao.selectByPrimaryKey(orderDetail.getOdaItyId());
            material = materialsDao.selectByPrimaryKey(orderDetail.getOdaMatId());

            // 校验是否满足红冲条件
            errorReason = checkRedValidate(order, orderDetail, inventory, material);
            if (errorReason.length() == 0) {

                //满足冲单条件 执行冲单操作
                redOrderDetailMethod(order, orderDetail, inventory);
                successCount++;
            } else {
                msg = msg + errorReason;
                errorCount++;
                continue;
            }
        }

        logService.saveLog("单据明细批量红冲", "红冲成功：" + successCount + "条, 红冲失败：" + errorCount + "条");

        String returnMsg;
        if (msg.length() > 0) {
            // 有异常数据
            returnMsg = "红冲成功：" + successCount + "条, 红冲失败：" + errorCount + "条。<br>" + msg + "<br> 以上数据红冲失败！";
        } else {
            returnMsg = "红冲成功！";
        }

        return returnMsg;
    }

    /**
     * 满足冲单条件 执行冲单操作
     *
     * @param order       主单
     * @param orderDetail 明细
     * @param inventory   出库在库
     */
    private void redOrderDetailMethod(MOrder order, MOrderDetail orderDetail, MInventory inventory) {
        MChangeOrder changeOrder;

        // 更改明细红字显示状态（oda_red_flag 是否红字显示： 1否 2是；oda_ity_flag 单据明细类型：1：蓝单 2：红单）
        orderDetail.setOdaRedFlag(2);
        orderDetail.setOdaRedDate(new Date());
        orderDetail.setOdaRedUser(ShiroUtils.getUser().getName());
        orderDetailDao.updateByPrimaryKey(orderDetail);

        // 插入一条新的单据红冲明细记录
        MOrderDetail redOrderDetail = new MOrderDetail();
        redOrderDetail.setOdaInType(orderDetail.getOdaInType());
        redOrderDetail.setOdaProCode(orderDetail.getOdaProCode());
        redOrderDetail.setOdaProName(orderDetail.getOdaProName());
        redOrderDetail.setOdaNum(orderDetail.getOdaNum());
        redOrderDetail.setOdaWeight(orderDetail.getOdaWeight());
        redOrderDetail.setOdaBackDate(orderDetail.getOdaBackDate());
        redOrderDetail.setOdaTrackCode(orderDetail.getOdaTrackCode());
        redOrderDetail.setOdaOdrId(orderDetail.getOdaOdrId());
        redOrderDetail.setOdaMatId(orderDetail.getOdaMatId());
        redOrderDetail.setOdaSpec(orderDetail.getOdaSpec());
        redOrderDetail.setOdaBackWeight(orderDetail.getOdaBackWeight());
//        redOrderDetail.setOdaPrice(orderDetail.getOdaPrice());
        redOrderDetail.setOdaItyId(orderDetail.getOdaItyId());
        redOrderDetail.setOdaItyFlag(2);
        redOrderDetail.setOdaRedFlag(2);
        redOrderDetail.setOdaRedDate(new Date());
        redOrderDetail.setOdaRedUser(ShiroUtils.getUser().getName());
//        redOrderDetail.setOdaAmount(orderDetail.getOdaAmount());
        redOrderDetail.setOdaMatSapCode(orderDetail.getOdaMatSapCode());
        orderDetailDao.insert(redOrderDetail);

        // 执行库存在库表数据变更(odr_type 入出库类型  1采购入库 2退料入库 4领料出库)
        if (order.getOdrType() == 1 || order.getOdrType() == 2 || order.getOdrType() == 6) {
            inventoryService.redInOrderDetail(inventory, orderDetail);
            if (order.getOdrType() == 6) {
                //回写调拨单状态
                AllocationOrder allocationOrder = new AllocationOrder();
                allocationOrder.setOdrCode(order.getOdrRepId());
                allocationOrder.setOdrOutStatus(2);
                allocationOrderDao.updateOutStatusByOdrCode(allocationOrder);
                //冲主单
                MOrder mOrder = new MOrder();
                mOrder.setOdrId(order.getOdrId());
                mOrder.setOdrItyFlag(2);
                orderDao.updateByPrimaryKeySelective(mOrder);
            }
        } else if (order.getOdrType() == 4 || order.getOdrType() == 5) {
            inventoryService.redOutOrderDetail(inventory, orderDetail);

            // 如果是串料出库 则更新串料出库状态为 已执行（未出库）状态
            if (inventory.getItyCeoSourceFlag() != null && inventory.getItyCeoSourceFlag() == 1) {
                changeOrder = new MChangeOrder();
                changeOrder.setCeoStatus(3);    // 0删除 1保存 2提交 3执行 4已出库 5归还中 6已归还 7被驳回

                MChangeOrderExample ex = new MChangeOrderExample();
                MChangeOrderExample.Criteria criteria = ex.createCriteria();
                criteria.andCeoStatusEqualTo(4);  // 已出库
                criteria.andCeoNeedItyIdEqualTo(inventory.getItyId());  // 库存在库id
                changeOrderDao.updateByExampleSelective(changeOrder, ex);
            }
            if (order.getOdrType() == 5) {
                //回写调拨单状态
                AllocationOrder allocationOrder = new AllocationOrder();
                allocationOrder.setOdrCode(order.getOdrRepId());
                allocationOrder.setOdrOutStatus(1);
                allocationOrderDao.updateOutStatusByOdrCode(allocationOrder);
                //冲主单
                MOrder mOrder = new MOrder();
                mOrder.setOdrId(order.getOdrId());
                mOrder.setOdrItyFlag(2);
                orderDao.updateByPrimaryKeySelective(mOrder);
            }
        }
    }

    /**
     * 校验是否满足红冲条件
     *
     * @param order       主单
     * @param orderDetail 明细
     * @param inventory   出库在库
     * @return
     */
    private String checkRedValidate(MOrder order, MOrderDetail orderDetail, MInventory inventory, MMaterials material) {

        String errorReason = "";
        // 如果已经被红冲，不允许二次红冲(oda_red_flag 红冲标识: 0蓝字 1被红冲)
        // 提示信息：单据号 项目号 原料描述 失败原因
        if (orderDetail.getOdaRedFlag() == 2) {

            errorReason = errorReason + "<br>" + order.getOdrCode() + "  " + orderDetail.getOdaProCode() + "  " + material.getMatNameDesc() + "  已经被红冲";
        }

        // 如果入库单红冲，判断可用库存是否充足(odr_type 入出库类型  1采购入库 2退料入库 4领料出库)
        if (order.getOdrType() == 1 || order.getOdrType() == 2) {
            if (inventory == null || inventory.getItyAvaNum() < orderDetail.getOdaNum()
                    || inventory.getItyAvaWeight() < orderDetail.getOdaWeight()) {
                errorReason = errorReason + "<br>" + order.getOdrCode() + "  " + orderDetail.getOdaProCode() + "  " + material.getMatNameDesc() + "  可用在库库存量不足";
            }
        }

        return errorReason;
    }


    public List<JMaterialAllModel> findStorage(JMaterialAllModel jMaterialAllModel, List<String> matTypeIdList, List<String> matQualityIdList, List<String> matSpecIdList, List<String> whiIdList) {

        StringBuilder sb;

        // 类型多选条件
        if (matTypeIdList != null && matTypeIdList.size() > 0) {
            sb = new StringBuilder();
            for (int i = 0; i < matTypeIdList.size(); i++) {
                sb.append(matTypeIdList.get(i)).append(",");
            }
            jMaterialAllModel.setMatTypeIdQueryList("'" + StringUtils.join(sb.toString().substring(0, sb.toString().length() - 1).split(","), "','") + "'");
        }
        // 材质多选条件
        if (matQualityIdList != null && matQualityIdList.size() > 0) {
            sb = new StringBuilder();
            for (int i = 0; i < matQualityIdList.size(); i++) {
                sb.append(matQualityIdList.get(i)).append(",");
            }
            jMaterialAllModel.setMatQualityIdQueryList("'" + StringUtils.join(sb.toString().substring(0, sb.toString().length() - 1).split(","), "','") + "'");
        }
        // 规格多选条件
        if (matSpecIdList != null && matSpecIdList.size() > 0) {
            sb = new StringBuilder();
            for (int i = 0; i < matSpecIdList.size(); i++) {
                sb.append(matSpecIdList.get(i)).append(",");
            }
            jMaterialAllModel.setMatSpecIdQueryList("'" + StringUtils.join(sb.toString().substring(0, sb.toString().length() - 1).split(","), "','") + "'");
        }
        if (whiIdList != null && whiIdList.size() > 0) {
            sb = new StringBuilder();
            for (int i = 0; i < whiIdList.size(); i++) {
                sb.append(whiIdList.get(i)).append(",");
            }
            jMaterialAllModel.setWhiIdQueryList("'" + StringUtils.join(sb.toString().substring(0, sb.toString().length() - 1).split(","), "','") + "'");
        }
        if (jMaterialAllModel.getWhiIdQueryList() != null && jMaterialAllModel.getWhiIdQueryList().equals("''")) {
            jMaterialAllModel.setWhiIdQueryList(null);
        }
        if (jMaterialAllModel.getWhiIdListStr() != null && jMaterialAllModel.getWhiIdListStr().equals("")) {
            jMaterialAllModel.setWhiIdListStr(null);
        }
        List<JMaterialAllModel> list = null;
        try {
            list = materialInDao.findComplexStorage(jMaterialAllModel);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return list;
    }


}
